#-*-coding:utf-8-*-
'''
This module is used to encode the string by using run length method.
@Author liuhucheng
@Time 14/05/2012 16:34
'''
from fileoperate import FileOperate

class RunLengthEncode:
    '''
    Encoding by length of bits
    '''
    def __init__(self):
        pass

    def Encoding(self,Instr):
        '''
        Instr is a string.
        '''
        fileop = FileOperate()
        #print len(Instr)
        bitsIn = fileop.BytesToBits(Instr)
        #print bitsIn
        #add a zero at first,to ensure the buffer is started by zero!
        scount = 1
        np = 0
        outstr = ''
        for i in bitsIn:
            if i == np:
                scount += 1
                if scount == 255:       #if the length beyond 255 bits,the program will add a bit which isn't the same as the previous one.
                    outstr += chr(scount)
                    if np != 1:
                        np = 1
                    else:
                        np = 0
                    scount = 1
            else:
                np = i
                outstr += chr(scount)
                scount = 1          # a new run length
        else:
            outstr += chr(scount)       #record the last bits
        outstr += '\0'
        return outstr

    def Decoding(self,Instr):
        '''
        Decode the str.The Instr should be end up with '\0'.
        '''
        if Instr[-1] != '\0':
            return None
        else:
            outlist = list()
            np = 0  #record the bits.
            pr = 0  #record last run length
            lent = len(Instr)
            for i in range(lent - 1):
                if i == 0:
                    outlist.extend([np for k in range(ord(Instr[i]) - 1)])
                    #pr = Instr[i]
                    np = 1
                else:
                    if pr != 255:
                        j = 0
                    else:
                        j = -1
                    outlist.extend([np for k in range(ord(Instr[i]) + j)])
                    if np != 0:         #normal situation
                        np = 0
                    else:
                        np = 1
                pr = ord(Instr[i])
            fileop = FileOperate()
            otrstr = fileop.BitsToBytes(outlist)
        return otrstr

    def test(self):
        '''
        test this module!
        '''
        avf = open('p.txt','rb')
        c = avf.read()
        avf.close()

        enstr = self.Encoding(c)
        avf = open('encoding.txt','wb')
        avf.write(enstr)
        avf.flush()
        avf.close()

        destr = self.Decoding(enstr)
        avf = open('decoding.txt','wb')
        avf.write(destr)
        avf.flush()
        avf.close()

if __name__ == "__main__":
    k = RunLengthEncode()
    k.test()
